/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//   PROGRAM TO EXECUTE HISTORY COMMANDS
//  1> !# (# is the number)
//  2> !! (history command)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

#include<iostream>
#include<string.h>
#include<stdlib.h>
#include<unistd.h>
#include<sys/types.h>

using namespace std;
extern char **environ;   //used for execvp

int main()
{
 char history[10][80];   //this array stores history of commands
 char cmd[80],tkn[25];
 int i=0,hist=0,num;

//-----------------------------------------   REMAINS IN WHILE LOOP 2 DISPLAY shell> ----------------------------------------------------

while(1)
{
 cout<<"\nshell> ";
 gets(cmd);   //accepting commands from user @ shell
     
char del[]= " ";
char *arg=strtok(cmd,del);
strcpy(tkn,arg);
     
/////////////////////////////////////////   To check wether it is !# and not  !! command ////////////////////////////////////////////////////

 if(tkn[0]=='!' && tkn[1]!='!')
  {
     int s;
     for(s=0;s<strlen(cmd);s++)
        {
           cmd[s]=cmd[s+1];
        }

     num=atoi(cmd);     //converting string to number to execute the exact command

                       //if requested command from history is more than the stored number of commands
     if(num>hist)
          cout<<"\nNumber of commands in history are less"<<endl;

     else
        {
          
           strcpy(history[i],history[num-1]);
           i++;
           hist++;
           char del[]= " ";
           char bgrd[80];
           char *arg=strtok(history[num-1],del);
   

   	    while(arg!=NULL)    //to check wethere there is "&" at last
           {
	       strcpy(bgrd,arg);
              arg=strtok(NULL,del);
           }
          

          if(fork()==0)  //fork to execute the command
            {
              int k=0,t;
              char *cmd2[50];
              char delims[] = " ";
              char *result=strtok(history[num-1],delims);
              cmd2[k]=result;
              cout<<"\nCommand:"<<history[num-1]<<endl;    //print the command from history to be executed

//-------------------------------------------  PARSING THE COMMAND FOR execvp in cmd2 array ------------------------------------------

              while( result !=NULL)  
                 {
		      strcpy(cmd2[k],result);
                    result=strtok(NULL,delims);
                    k++;
                 }

             cmd2[k]=(char*)0;   //execvp needs MULL terminated array

             execvp(cmd2[0],cmd2);   //actual command is executed here for !# #-->any number
           }
 
           else
            {
               if(strcmp(bgrd,"&")!=0)   // if "&" at last shell will not wait untill complete execution of command
                 wait(NULL);
            }
        }
  }
      
//------------------------------------------ IF EXIT ------------------------------------------------------------

 else if(strcmp(cmd,"exit")==0)
        break;
//------------------------------------------  IF HISTORY COMMAND ------------------------------------------------

 else if(strcmp(cmd,"history")==0)
  {

///////////////////////////////////////////  PRINTING THE NUMBER AND COMMANDS IN HISTORY  /////////////////////////////////////

    for(int j=0;j<i;j++)
      {
         cout<<"\n"<<j+1<<" "<<history[j];
      }
 } //end of if

////////////////////////////////////////// IF !! COMMAND THEN EXECUTE THE LAST COMMAND //////////////////////////////////////

 else if(strcmp(cmd,"!!")==0)
  {
     if(hist!=0)
     {
       int l=0;
       char del[]= " ";
       char bgrd[80];
       char *arg=strtok(history[i-1],del);
   
///////////////////////////////////////  TO CHECK "&" at last ///////////////////////////////////////////////////

    while(arg!=NULL)
    {
	 strcpy(bgrd,arg);
        arg=strtok(NULL,del);
    }

       int pid;
       int cnt=i-1;

       strcpy(history[i],history[cnt]);  //Storing the respective command in history
       i++;
       hist++;
             
       if((pid=fork())==0)  //fork to execute the command
         {
            int k=0,t;
            char *cmd2[50];
            char delims[] = " ";
            char *result=strtok(history[cnt],delims);
              cmd2[k]=result;
            cout<<"\nCommand:"<<history[cnt]<<endl;

///////////////////////////////////////////////////// PARSING THE COMMAND ///////////////////////////////////////

            while( result !=NULL)
                 {
		      strcpy(cmd2[k],result);
                    result=strtok(NULL,delims);
                    k++;
                 }
            cmd2[k]=(char*)0;
            
            execvp(cmd2[0],cmd2);   //executing the command here
         } //end of fork

        else
          {
          if(strcmp(bgrd,"&")!=0)
              wait(NULL);
          }
     }// end of if(hist!=0)
  } //end of else if

else
{
char test[80];
strcpy(test,cmd);
strcat(test," > 1");
 if(system(test)==0)     //to check wether command is valid or invalid
  {
    strcpy(history[i],cmd);
    i=i+1;
    hist++;
    if(i==9)
       i=0;
  }

 char del[]= " ";
       char bgrd[80];
       char *arg=strtok(cmd,del);
   

    while(arg!=NULL)   // FOR "&"
    {
	 strcpy(bgrd,arg);
        arg=strtok(NULL,del);
    }

       int pid;
             
       if((pid=fork())==0)  //fork for execution of command
         {
            int k=0,t;
            char *cmd2[50];
            char delims[] = " ";
            char *result=strtok(cmd,delims);
              cmd2[k]=result;
            
            while( result !=NULL)  //parsing the command
                 {
		      strcpy(cmd2[k],result);
                    result=strtok(NULL,delims);
                    k++;
                 }
            cmd2[k]=(char*)0;
            
            execvp(cmd2[0],cmd2);  //executing the command here
         } //end of fork

       else
          {
            if(strcmp(bgrd,"&")!=0)
               wait(NULL);
          }
            
}// end of else

} //end of while

return 0;
} //end of main
